package org.budo.redis.jdbc.driver;

import java.net.URI;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import org.budo.jdbc.driver.AbstractBudoJdbcDriver;
import org.budo.jdbc.driver.parser.SqlStatementParser;
import org.budo.jdbc.driver.parser.cache.CachedJdbcStatementParser;
import org.budo.redis.jdbc.driver.executor.AbstractRedisStatementExecutor;
import org.budo.redis.jdbc.driver.parser.impl.DefaultRedisStatementParser;

/**
 * 入口类，实现了java.sql.Driver接口
 * 
 * @author lmw
 */
public class BudoRedisJdbcDriver extends AbstractBudoJdbcDriver {
    private static final SqlStatementParser DEFAULT_STATEMENT_PARSER = new CachedJdbcStatementParser().statementParser(new DefaultRedisStatementParser());

    private static final String JDBC = "jdbc:";

    public static final String URL_PREFIX = JDBC + "redis:";

    private static final String DEFAULT_HOST = "127.0.0.1";

    private static final int DEFAULT_PORT = 6379;

    private static final int DEFAULT_DB = 0;

    static {
        try {
            BudoRedisJdbcDriver driver = new BudoRedisJdbcDriver();
            DriverManager.registerDriver(driver); // 类加载时注册驱动
        } catch (Throwable e) {
            throw new IllegalStateException("#38 Can't register driver!", e);
        }
    }

    /**
     * 获取连接
     * 
     * @param url 形如 jdbc:redis://127.0.0.1:6379/0
     */
    @Override
    public Connection connect(String url, Properties info) throws SQLException {
        if (null == url || !url.startsWith(URL_PREFIX)) {
            throw new SQLException("#33 Invalid URL: " + url);
        }

        String rawUrl = url.replaceFirst(JDBC, "");

        String host = DEFAULT_HOST;
        int port = DEFAULT_PORT;
        int db = DEFAULT_DB;

        try {
            URI uri = new URI(rawUrl);

            host = uri.getHost() != null ? uri.getHost() : DEFAULT_HOST;
            port = uri.getPort() > 0 ? uri.getPort() : DEFAULT_PORT;

            if (uri.getPath() != null && uri.getPath().length() > 1) {
                db = Integer.parseInt(uri.getPath().substring(1));
            }
        } catch (Throwable e) {
            throw new SQLException("#61 Invalid URL: " + url, e);
        }

        String password = null;
        if (null != info) {
            password = info.getProperty("password");
        }

        AbstractRedisStatementExecutor statementExecutor = this.statementExecutor();
        statementExecutor.setHost(host);
        statementExecutor.setPort(port);
        statementExecutor.setPassword(password);
        statementExecutor.setDb(db);

        BudoRedisJdbcConnection connection = new BudoRedisJdbcConnection();
        connection.setCatalog(db + "");
        connection.setStatementParser(DEFAULT_STATEMENT_PARSER);
        connection.setStatementExecutor(statementExecutor);
        return connection;
    }

    protected AbstractRedisStatementExecutor statementExecutor() {
        // return new org.budo.redis.jdbc.driver.executor.jedis.BudoJedisRedisStatementExecutor();
        return new org.budo.redis.jdbc.driver.executor.socket.BudoSocketRedisStatementExecutor();
    }
}